/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package mysgoog.brown.dragon;

import java.util.*;
import mysgoog.brown.*;

public class Worm_data {

	// Only origin and color will be propagated !
	public int origin; /*
						 * the origin of the string. if color is empty, origin
						 * is meaningless
						 */
	public int color; /* its color */

	public int size; /* its cardinality */
	public int[] stones = new int[Brown.maxSize]; /*
												 * the same worm iff they have
												 * same origin.
												 */
	public int libn; /* number of liberties */
	public int[] libs = new int[Brown.maxSize]; /*
												 * all the libierties of this
												 * womr
												 */

	public Worm_data() {
		color = Brown.EMPTY;
		size = 0;
	}

	public void clear() {
		color = Brown.EMPTY;
		size = 0;
	}

	private static boolean[] stMark = new boolean[Brown.maxSize];
	private static boolean[] libMark = new boolean[Brown.maxSize]; // liberties
	private static int[] wstone = new int[Brown.maxSize];
	private static int[] wlibs = new int[Brown.maxSize];

	/*
	 * assume board, next_stone in Brown have been updated correctly only build
	 * one worm
	 */
	static private void calculate(int pos, int color) {
		Arrays.fill(libMark, 0, size(), false);
		int stn = 0;
		int next = pos;
		do {
			// Lib.log("beg\t"+next+" \n");
			for (int k = 0; k < 4; ++k) {
				int ai = Brown.I(next) + Brown.deltai[k];
				int aj = Brown.J(next) + Brown.deltaj[k];
				int apos = Brown.POS(ai, aj);
				if (Brown.on_board(ai, aj) && Brown.board[apos] == Brown.EMPTY) {
					libMark[apos] = true;
				}
			}

			wstone[stn++] = next;

			DragonMgr.worms[next].color = color;
			DragonMgr.worms[next].origin = pos;

			next = Brown.next_stone[next];
		} while (next != pos);

		int lbn = 0;
		for (int k = 0; k < size(); ++k) {
			if (libMark[k])
				wlibs[lbn++] = k;
		}
		DragonMgr.worms[pos].size = stn;
		DragonMgr.worms[pos].libn = lbn;
		System.arraycopy(wstone, 0, DragonMgr.worms[pos].stones, 0, stn);
		System.arraycopy(wlibs, 0, DragonMgr.worms[pos].libs, 0, lbn);
	}

	/*
	 * used in DragonMgr to update worms[] assume board, next_stone in Brown
	 * have been updated correctly fixed by wxa
	 */
	static public void addUpdate(int pos, int color) {
		// Lib.log("123\n");
		calculate(pos, color);
		// Lib.log("aaaaaaaa\n");
		int opp_color = Brown.OTHER_COLOR(color);
		for (int k = 0; k < 4; ++k) {
			int ai = Brown.I(pos) + Brown.deltai[k];
			int aj = Brown.J(pos) + Brown.deltaj[k];
			int apos = Brown.POS(ai, aj);
			if (Brown.on_board(ai, aj) && Brown.board[apos] == opp_color) {
				calculate(apos, opp_color);
			}
		}
		// Lib.log("456\n");
	}

	/*
	 * used in DragonMgr to update worms[] assume board, next_stone in Brown
	 * have been updated correctly remove entire worm fixed by wxa
	 */
	static public void removeUpdate(int org) {
		Lib.assertTrue(DragonMgr.worms[org].origin == org);
		Arrays.fill(stMark, 0, size(), false);

		int size = DragonMgr.worms[org].size;
		DragonMgr.worms[org].size = 0;
		DragonMgr.worms[org].libn = 0;

		for (int k0 = 0; k0 < size; ++k0) {
			int next = DragonMgr.worms[org].stones[k0];
			for (int k = 0; k < 4; ++k) {
				int ai = Brown.I(next) + Brown.deltai[k];
				int aj = Brown.J(next) + Brown.deltaj[k];
				int apos = Brown.POS(ai, aj);
				if (Brown.on_board(ai, aj) && Brown.board[apos] != Brown.EMPTY
						&& DragonMgr.worms[apos].origin != org) {
					stMark[DragonMgr.worms[apos].origin] = true;
				}
			}
			DragonMgr.worms[next].color = Brown.EMPTY;
		}

		for (int k = 0; k < size(); ++k) {
			if (stMark[k])
				calculate(k, Brown.board[k]);
		}
	}

	static private int size() {
		return Brown.board_size * Brown.board_size;
	}
}
